package com.fmy.jurisdiction.modular.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fmy.jurisdiction.core.commons.consts.SystemConsts;
import com.fmy.jurisdiction.core.commons.kits.BizExceptionKit;
import com.fmy.jurisdiction.core.commons.kits.MybatisPlusKit;
import com.fmy.jurisdiction.core.commons.status.PermissionType;
import com.fmy.jurisdiction.core.unusual.BizException;
import com.fmy.jurisdiction.modular.mapper.AdminRolePermMapper;
import com.fmy.jurisdiction.modular.model.AdminPermission;
import com.fmy.jurisdiction.modular.mapper.AdminPermissionMapper;
import com.fmy.jurisdiction.modular.model.AdminRolePerm;
import com.fmy.jurisdiction.modular.model.vo.AdminPermissionChildren;
import com.fmy.jurisdiction.modular.service.IAdminPermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fmy.jurisdiction.modular.service.IAdminUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 权限表  服务实现类
 * </p>
 *
 * @author Mr.fmy
 * @since 2019-09-16
 */
@Service
public class AdminPermissionServiceImpl extends ServiceImpl<AdminPermissionMapper, AdminPermission> implements IAdminPermissionService {

    @Autowired
    private IAdminUserService userService;
    @Autowired
    private AdminRolePermMapper rolePermMapper;

    @Override
    public Set<String> getPermCode(Integer uid) {
        String roles = userService.getRoles(uid);
        return rolePermMapper.findByRoleIdToPermCode(Convert.toList(Integer.class, roles));
    }

    @Override
    public List<AdminPermissionChildren> getChilds(Integer uid, PermissionType type) {
        List<AdminPermission> permissions = rolePermMapper
                .findByRoleIdToPrem(uid != null ? Convert.toList(Integer.class, userService.getRoles(uid)) : null, //第一个参数
                        type != null ? type.getValue() : null);//第二个参数
        List<AdminPermissionChildren> childs = new ArrayList<>();
        int topLevel = permissions.size() > 1 ? permissions.stream().mapToInt(item -> item.getLevel()).min().getAsInt() : permissions.get(0).getLevel();
        //循环出来一级菜单
        permissions.forEach(item -> {
            if (item.getLevel().equals(topLevel)) {
                AdminPermissionChildren child = new AdminPermissionChildren();
                BeanUtils.copyProperties(item, child);
                childs.add(child);
            }
        });
        //递归循环
        childs.forEach(item -> {
            item.setChildren(recursion(item.getCode(), permissions));
        });
        return childs;
    }

    @Override
    @Transactional
    public boolean add(AdminPermission permission) {
        //1、查询code是否存在
        BizExceptionKit.throwBusiness(this.count(MybatisPlusKit.<AdminPermission>q().eq(AdminPermission.CODE, permission.getCode())) > 0, "权限Code已经存在");
        //2、查询其父级
        if (!permission.getPcode().equals(SystemConsts.PERMISSION_TOP)) {
            AdminPermission pAuth = findByCode(permission.getPcode());
            BizExceptionKit.throwBusiness(pAuth == null, StrUtil.format("未查询Code的为{}的权限", permission.getPcode()));
            //赋值 Pcodes
            permission.setPcodes(pAuth.getPcodes() + SystemConsts.ROLE_PERMI_SEPARATOR + pAuth.getCode());
            permission.setLevel(pAuth.getLevel() + 1);
        } else {
            permission.setPcodes(SystemConsts.PERMISSION_TOP);
        }
        permission.setCreateTime(LocalDateTime.now());
        if (this.save(permission)) {
            if (rolePermMapper.insert(new AdminRolePerm(SystemConsts.ROLE_ADMIN_ID, permission.getId())) <= 0) {
                throw new BizException("新增权限失败、请重试");
            }
        }
        return true;
    }

    @Override
    public AdminPermission findByCode(String code) {
        return this.getOne(MybatisPlusKit.<AdminPermission>q().eq(AdminPermission.CODE, code));
    }

    @Override
    public Integer findByCodeToId(String code) {
        return this.getObj(MybatisPlusKit.<AdminPermission>q().select(AdminPermission.ID)
                .eq(AdminPermission.CODE, code), item -> NumberUtil.parseInt(item.toString()));
    }

    @Override
    public String findByIdToPcode(Integer id) {
        return this.getObj(MybatisPlusKit.<AdminPermission>q().select(AdminPermission.PCODE)
                .eq(AdminPermission.ID, id), item -> item.toString());
    }

    @Override
    public boolean modifyPerm(Integer id, String name, String url, String icon, PermissionType type, Integer optionUser) {
        UpdateWrapper<AdminPermission> u = MybatisPlusKit.u();
        u.eq(AdminPermission.ID, id)
                .set(AdminPermission.NAME, name).set(AdminPermission.ICON, icon)
                .set(AdminPermission.URL, StrUtil.isEmpty(url) ? "#" : url)
                .set(AdminPermission.TYPE, type == null ? PermissionType.JURISDICTION_TYPE : type)
                .set(AdminPermission.MODIFY_TIME, LocalDateTime.now())
                .set(AdminPermission.MODIFY_USER, optionUser);
        return this.update(u);
    }

    @Override
    @Transactional
    public boolean delPerm(Integer id) {
        String code = findByIdToPcode(id);
        BizExceptionKit.throwBusiness(this.count(MybatisPlusKit.<AdminPermission>q().like(AdminPermission.PCODES, code)) > 0, "该权限存在子权限不可强制删除");
        rolePermMapper.delete(MybatisPlusKit.<AdminRolePerm>q().eq(AdminRolePerm.PERMISSION_ID, id));//删除和角色的关联
        return this.removeById(id);//删除该权限
    }

    /**
     * 递归
     *
     * @param code        权限code
     * @param permissions 所有权限
     */
    private List<AdminPermissionChildren> recursion(String code, List<AdminPermission> permissions) {
        List<AdminPermissionChildren> childs = new ArrayList<>();
        permissions.forEach(item -> {
            if (item.getPcode().equals(code)) {
                AdminPermissionChildren child = new AdminPermissionChildren();
                BeanUtils.copyProperties(item, child);
                childs.add(child);
            }
        });
        childs.forEach(item -> {
            item.setChildren(recursion(item.getCode(), permissions));
        });
        return childs.size() == 0 ? null : childs;
    }
}
